package com.cxy.common.config;

import com.cxy.common.boot.CxyCloudConstants;
import com.cxy.common.util.NetUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.boot.env.RandomValuePropertySourceEnvironmentPostProcessor;
import org.springframework.boot.logging.DeferredLog;
import org.springframework.boot.logging.DeferredLogFactory;
import org.springframework.boot.logging.DeferredLogs;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.SimpleCommandLinePropertySource;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

/*********************************************************
 * 文件名称：CxyCloudBootstrapConfiguration.java
 * 系统名称：CXY自定义系统
 * 模块名称：com.cxy.common.config
 * 功能说明：参数配置
 * 开发人员 @author：caoxy31978
 * 开发时间 @date：2023/6/29 13:42
 * 修改记录：程序版本  修改日期  修改人员  修改单号  修改说明
 *********************************************************/
@Order(99)
public class CxyCloudBootstrapConfiguration implements EnvironmentPostProcessor{
    private final Log LOGGER;

    public CxyCloudBootstrapConfiguration(DeferredLogFactory logFactory) {
        this.LOGGER = logFactory.getLog(CxyCloudBootstrapConfiguration.class);
    }
    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        // 获得所有参数key
        List<String> keys = new ArrayList();
        MutablePropertySources propertySources = environment.getPropertySources();
        for (PropertySource<?> source : propertySources) {
            if (!(source instanceof OriginTrackedMapPropertySource) && !(source instanceof SimpleCommandLinePropertySource)) {
                continue;
            }
            keys.addAll(Arrays.asList(((EnumerablePropertySource<?>) source).getPropertyNames()));
        }
        //增加缺失的参数
        setMissingPropertyReference(keys,environment);

        Map<String, Object> map = new HashMap<>();
        for (String key : keys) {
            String value = environment.getProperty(key);
            if (StringUtils.isNotBlank(value)){
                // TODO 可以在这里进行配置转换 来支持加解密
                map.put(key, value);
                switch (key){
                    case CxyCloudConstants.APP_NAME:
                        map.put("spring.application.name", value);
                        break;
                    case "spring.application.name":
                        map.put(CxyCloudConstants.APP_NAME, value);
                        break;
                    case "app.server.port":
                        map.put("server.port", value);
                        break;
                    case "server.port":
                        map.put("app.server.port", value);
                        break;
                }
            }
        }
        int configPort = 0;
        try {
            configPort = Integer.parseInt(String.valueOf(map.get("server.port")));
        } catch (Exception e) {
            LOGGER.debug("未配置端口号或配置的端口号不正确，请检查");
        }
        if (configPort <= 0) {
            int port = NetUtils.getAvailablePort();
            map.put("server.port", port);
            map.put("app.server.port", port);
        }
        environment.getPropertySources().addFirst(new MapPropertySource("cxyCloudApplicationConfig", map));
    }
    private void setMissingPropertyReference(List<String> keys, ConfigurableEnvironment environment) {
        if (!keys.contains("project.version")) {
            Map<String, Object> version = new HashMap();
            version.put("project.version", "v");
            environment.getPropertySources().addLast(new MapPropertySource("ApplicationReferenceMissingConfig", version));
        }
    }
}
